/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package vn.webapp.service;

import algo.Common.DataOut;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import vn.webapp.dao.ClassesDAO;
import vn.webapp.dao.ClassingDAO;
import vn.webapp.dao.CoursingDAO;
import vn.webapp.dao.TimetablingDAO;
import vn.webapp.dao.ViewingDAO;
import vn.webapp.dto.DataPage;
import vn.webapp.model.Classes;
import vn.webapp.model.Classing;
import vn.webapp.model.ClassingTimeTabling;
import vn.webapp.model.CourseTeacherClass;
import vn.webapp.model.CoursesTimeTabling;
import vn.webapp.model.Coursing;
import vn.webapp.model.CoursingTimeTabling;
import vn.webapp.model.Timetabling;
import vn.webapp.model.Timetablingraw;

@Service("timetablingService")
public class TimetablingServiceImpl implements TimetablingService {

    @Autowired
    private TimetablingDAO timetablingDAO;
    @Autowired 
    private ClassesDAO classesDAO;
    
    @Autowired 
    private CoursingDAO coursingDAO;
    
    @Autowired 
    private ViewingDAO viewingDAO;

    public void setTimetablingDAO(TimetablingDAO timetablingDAO) {
        this.timetablingDAO = timetablingDAO;
    }

    public void setClassesDAO(ClassesDAO classesDAO) {
        this.classesDAO = classesDAO;
    }

    public void setCoursingDAO(CoursingDAO coursingDAO) {
        this.coursingDAO = coursingDAO;
    }
    
    
    @Override
    public DataPage<Timetabling> getAll() {
        DataPage<Timetabling> dataAllTimetabling = new DataPage<>();
        
        dataAllTimetabling.setData(timetablingDAO.getAll());
        return dataAllTimetabling;
    }
    
    @Override
    public DataPage<Timetabling> list() {
        DataPage<Timetabling> dataTimetabling = new DataPage<>();
        dataTimetabling.setData(timetablingDAO.list());
        
        /* Get all courseteacher id */
        List<CoursingTimeTabling> aCoursings = new ArrayList<>();
        //List<Classes> classeses = classesDAO.getByIds(cids);
        
        for(Timetabling c: dataTimetabling.getData()){
           //aCoursings.add(c.getCoursing());
           aCoursings.add(c.getCoursing());
           /* Get all courseteacher id */
           List<List<ClassingTimeTabling>> aClassings = new ArrayList<>();
            //List<Classes> classeses = classesDAO.getByIds(cids);

            for(CoursingTimeTabling cc: aCoursings){
                aClassings.add(cc.getClassing());
                List<Integer> classIds = new ArrayList<>();
                for(ClassingTimeTabling cls : cc.getClassing())
                {
                    classIds.add(cls.getClass_id());
                }
                List<Classes> classeses = classesDAO.getByIds(classIds);
                cc.setClasses(classeses);
            }
        }
        DataPage<Timetabling> aa = dataTimetabling;
        return dataTimetabling;
    }
    
    @Override
    public List<Timetablingraw> listRaw()
    {
        DataPage<Timetablingraw> dataTimetabling = new DataPage<>();
        dataTimetabling.setData(timetablingDAO.listRaw());
        
        return (List<Timetablingraw>) dataTimetabling.getData();
    }
    
    @Override
    public List<CourseTeacherClass> listViewing()
    {
        DataPage<CourseTeacherClass> dataTimetabling = new DataPage<>();
        dataTimetabling.setData(viewingDAO.listViewing());
        
        return (List<CourseTeacherClass>) dataTimetabling.getData();
    }
    
    @Override
    public List<CourseTeacherClass> listViewingByClassId(int classId)
    {
        DataPage<CourseTeacherClass> dataTimetabling = new DataPage<>();
        dataTimetabling.setData(viewingDAO.getByClassId(classId));
        
        return (List<CourseTeacherClass>) dataTimetabling.getData();
    }
    
    @Override
    public DataPage<Timetabling> listMorning() {
        DataPage<Timetabling> dataTimetabling = new DataPage<>();
        dataTimetabling.setData(timetablingDAO.list());
        return dataTimetabling;
    }
    
    @Override
    public DataPage<Timetabling> listAfternoon() {
        DataPage<Timetabling> dataTimetabling = new DataPage<>();
        dataTimetabling.setData(timetablingDAO.list());
        return dataTimetabling;
    }
    
    @Override
    public int removeATimetabling(int id){
        return timetablingDAO.removeATimetabling(id);
    }
    
    @Override
    public int checkExists(int id, Coursing coursing, int coursingId, int roomId, int day, int slot){
        int iExists = 0;
        for(Classing classing : coursing.getClassing())
        {
            Timetablingraw tbl = timetablingDAO.checkExists(id, coursingId, roomId, day, slot, classing.getClass_id());
            if(tbl != null)
                iExists++;
        }
        return iExists;
    }
    
    @Override
    public int saveATimetabling(Coursing coursing, int roomId, int day, int slot, int timerange){
        
        Timetablingraw timetabling = new Timetablingraw();
        //timetabling.setCourseteacher_id(coursingId);
        timetabling.setDay(day);
        timetabling.setSlot(slot);
        timetabling.setRoom_id(roomId);
        timetabling.setTimerange(timerange);
        timetabling.setCourse_id(coursing.getCourse_id());
        timetabling.setTeacher_id(coursing.getTeacher_id());
        timetabling.setSession_id(coursing.getSession_id());
        timetabling.setCourseteacher_id(coursing.getCourseteacher_id());
        int id = 0;
        for(Classing classing : coursing.getClassing())
        {
            timetabling.setClass_id(classing.getClass_id());
            id += timetablingDAO.saveATimetabling(timetabling);
        }
        return id;
    }

    @Override
    public void editATimetabling(int id, Coursing coursing, int coursingId, int roomId, int day, int slot, int timerange){
        
        Timetablingraw timetabling = new Timetablingraw();
        timetabling.setTimetabling_id(id);
        timetabling.setCourseteacher_id(coursingId);
        timetabling.setDay(day);
        timetabling.setSlot(slot);
        timetabling.setRoom_id(roomId);
        timetabling.setTimerange(timerange);
        timetabling.setCourse_id(coursing.getCourse_id());
        timetabling.setTeacher_id(coursing.getTeacher_id());
        timetabling.setSession_id(coursing.getSession_id());
        timetabling.setCourseteacher_id(coursing.getCourseteacher_id());
        for(Classing classing : coursing.getClassing())
        {
            timetabling.setClass_id(classing.getClass_id());
            timetablingDAO.editATimetabling(timetabling);
        }
        
//        Classing classing = new Classing();
//        classing.setId(classingId);
//        classing.setCourseteacherid(id);
//        classing.setClassid(classId);
//        
//        classingDAO.editAClassing(classing);
    }
    
    @Override
    public DataPage<Timetabling> filter(int page, int pageSize) {
        DataPage<Timetabling> dataTimetabling = new DataPage<>();
        dataTimetabling.setPageIndex(page);
        dataTimetabling.setPageSize(pageSize); 
        dataTimetabling.setDataCount(timetablingDAO.count());
        dataTimetabling.setPageCount(dataTimetabling.getDataCount()/pageSize);
        if(dataTimetabling.getDataCount()%pageSize > 0){
            dataTimetabling.setPageCount(dataTimetabling.getPageCount()+1);
        }
        dataTimetabling.setData(timetablingDAO.filter(page, pageSize));
        
        /* Get all courseteacher id */
        List<CoursingTimeTabling> aCoursings = new ArrayList<>();
        //List<Classes> classeses = classesDAO.getByIds(cids);
        
        for(Timetabling c: dataTimetabling.getData()){
           List<CoursingTimeTabling> ctb = coursingDAO.getByIdTimetabling(c.getCourseteacher_id());
           //List<Coursing> csc = (List<Coursing>) new HashSet<Coursing>(coursingDAO.getById(c.getCourseteacher_id()));
           //CoursingTimeTabling aa = ctb.get(0);
           c.setCoursing(ctb.get(0));
            //aCoursings.add(c.getCoursing());
           aCoursings.add(ctb.get(0));
           /* Get all courseteacher id */
           List<List<ClassingTimeTabling>> aClassings = new ArrayList<>();
            //List<Classes> classeses = classesDAO.getByIds(cids);

            for(CoursingTimeTabling cc: aCoursings){
                aClassings.add(cc.getClassing());
                List<Integer> classIds = new ArrayList<>();
                for(ClassingTimeTabling cls : cc.getClassing())
                {
                    classIds.add(cls.getClass_id());
                }
                List<Classes> classeses = classesDAO.getByIds(classIds);
                cc.setClasses(classeses);
            }
        }
        DataPage<Timetabling> aa = dataTimetabling;
        return dataTimetabling;
    }
    
    public String executeAlgorithm()
    {
        try{
            FileDemo file = new FileDemo();
            String abc = "files";
            file.main(abc);
        }catch(IOException e)
        {
            System.out.println(e.getMessage());
            return e.getMessage();
        }
        return "successfully";
    }
    
    @Override
    public int saveAtimetablingAuto (DataOut _outputTimetabling, int randomCourseId)
    {
         Timetablingraw timetabling = new Timetablingraw();
        //timetabling.setCourseteacher_id(coursingId);
        timetabling.setDay(_outputTimetabling.getDayTime());
        timetabling.setSlot(_outputTimetabling.getSlot());
        timetabling.setRoom_id(_outputTimetabling.getRoomId());
        timetabling.setCourse_id(_outputTimetabling.getCourseId());
        timetabling.setTeacher_id(_outputTimetabling.getTeacherId());
        timetabling.setSession_id(_outputTimetabling.getSessionId());
        timetabling.setClass_id(_outputTimetabling.getClassId());
        Coursing courseTeacher = coursingDAO.getByTeacherCourseSession(_outputTimetabling.getTeacherId(), _outputTimetabling.getCourseId(), _outputTimetabling.getSessionId());
        if(courseTeacher != null)
        {
            timetabling.setCourseteacher_id(courseTeacher.getCourseteacher_id());
            return timetablingDAO.saveATimetabling(timetabling);
        }else
        {
            timetabling.setCourseteacher_id(randomCourseId);
            timetablingDAO.saveATimetabling(timetabling);
        }
        return 0;
    }
    
    @Override
    public int truncateOldData(){
        return timetablingDAO.truncateOldData();
    }
    
    @Override
    public void truncateAllOldata(List<Timetabling> listTimetabling)
    {
        for(Timetabling tbl : listTimetabling)
        {
            timetablingDAO.removeATimetabling(tbl.getTimetabling_id());
        }
    }
}
